1 /* 2 * Copyright 2002-2013 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.test.context.junit4.spr9051; 18 19 import javax.sql.DataSource; 20 21 import org.junit.Before; 22 23 import org.springframework.context.annotation.Bean; 24 import org.springframework.context.annotation.Configuration; 25 import org.springframework.jdbc.core.JdbcTemplate; 26 import org.springframework.jdbc.datasource.DataSourceTransactionManager; 27 import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; 28 import org.springframework.test.context.ContextConfiguration; 29 import org.springframework.test.context.transaction.AfterTransaction; 30 import org.springframework.test.context.transaction.TransactionalTestExecutionListener; 31 import org.springframework.tests.sample.beans.Employee; 32 import org.springframework.transaction.PlatformTransactionManager; 33 34 import static org.junit.Assert.*; 35 36 /** 37 * Concrete implementation of {@link AbstractTransactionalAnnotatedConfigClassTests} 38 * that does <b>not</b> use a true {@link Configuration @Configuration class} but 39 * rather a <em>lite mode</em> configuration class (see the Javadoc for {@link Bean @Bean} 40 * for details). 41 * 42 * @author Sam Brannen 43 * @since 3.2 44 * @see Bean 45 * @see TransactionalAnnotatedConfigClassWithAtConfigurationTests 46 */ 47 @ContextConfiguration(classes = TransactionalAnnotatedConfigClassesWithoutAtConfigurationTests.AnnotatedFactoryBeans.class) 48 public class TransactionalAnnotatedConfigClassesWithoutAtConfigurationTests extends 49 AbstractTransactionalAnnotatedConfigClassTests { 50 51 /** 52 * This is intentionally <b>not</b> annotated with {@code @Configuration}. 53 * 54 * <p>Consequently, this class contains <i>annotated factory bean methods</i> 55 * instead of standard singleton bean methods. 56 */ 57 // @Configuration 58 static class AnnotatedFactoryBeans { 59 60 @Bean 61 public Employee employee() { 62 Employee employee = new Employee(); 63 employee.setName("John Smith"); 64 employee.setAge(42); 65 employee.setCompany("Acme Widgets, Inc."); 66 return employee; 67 } 68 69 @Bean 70 public PlatformTransactionManager transactionManager() { 71 return new DataSourceTransactionManager(dataSource()); 72 } 73 74 /** 75 * Since this method does not reside in a true {@code @Configuration class}, 76 * it acts as a factory method when invoked directly (e.g., from 77 * {@link #transactionManager()}) and as a singleton bean when retrieved 78 * through the application context (e.g., when injected into the test 79 * instance). The result is that this method will be called twice: 80 * 81 * <ol> 82 * <li>once <em>indirectly</em> by the {@link TransactionalTestExecutionListener} 83 * when it retrieves the {@link PlatformTransactionManager} from the 84 * application context</li> 85 * <li>and again when the {@link DataSource} is injected into the test 86 * instance in {@link AbstractTransactionalAnnotatedConfigClassTests#setDataSource(DataSource)}.</li> 87 *</ol> 88 * 89 * Consequently, the {@link JdbcTemplate} used by this test instance and 90 * the {@link PlatformTransactionManager} used by the Spring TestContext 91 * Framework will operate on two different {@code DataSource} instances, 92 * which is almost certainly not the desired or intended behavior. 93 */ 94 @Bean 95 public DataSource dataSource() { 96 return new EmbeddedDatabaseBuilder()// 97 .addScript("classpath:/org/springframework/test/context/junit4/spr9051/schema.sql")// 98 // Ensure that this in-memory database is only used by this class: 99 .setName(getClass().getName())// 100 .build(); 101 } 102 103 } 104 105 106 @Before 107 public void compareDataSources() throws Exception { 108 // NOTE: the two DataSource instances are NOT the same! 109 assertNotSame(dataSourceFromTxManager, dataSourceViaInjection); 110 } 111 112 /** 113 * Overrides {@code afterTransaction()} in order to assert a different result. 114 * 115 * <p>See in-line comments for details. 116 * 117 * @see AbstractTransactionalAnnotatedConfigClassTests#afterTransaction() 118 * @see AbstractTransactionalAnnotatedConfigClassTests#modifyTestDataWithinTransaction() 119 */ 120 @AfterTransaction 121 @Override 122 public void afterTransaction() { 123 assertEquals("Deleting yoda", 1, deletePerson(YODA)); 124 125 // NOTE: We would actually expect that there are now ZERO entries in the 126 // person table, since the transaction is rolled back by the framework; 127 // however, since our JdbcTemplate and the transaction manager used by 128 // the Spring TestContext Framework use two different DataSource 129 // instances, our insert statements were executed in transactions that 130 // are not controlled by the test framework. Consequently, there was no 131 // rollback for the two insert statements in 132 // modifyTestDataWithinTransaction(). 133 // 134 assertNumRowsInPersonTable(2, "after a transactional test method"); 135 } 136 137 }